<?php
/**
 * Created on 07/01/2014
 * Description: 
 * 	Implements a simple static class logger.
 * 	Can show a message of one of the following log levels:
 * 		fatal, error, warn, info, debug, trace
 * 	
 * 	Threshold level shoul be defined in this class as LOGGING_LEVEL (globally) - can also be all or none (off)
 * 
 * 	Each message will print the regular error prefix (depend on the server's definitions),
 * 		then:
 * 		1. Massage level
 * 		2. File name
 * 		3. Line number
 * 		4. Class name (if there is)
 * 		5. Function name (if there is)
 * 
 * @author Aryeh Rein 
 */

class Logger
{
	const OFF = 0;
	const FATAL = 1;
	const ERROR = 2;	
	const WARN = 3;
	const INFO = 4;
	const DEBUG = 5;
	const TRACE = 6;
	const ALL = 7;
	
	const LOGGING_LEVEL = Logger::INFO;
	
	static private function log($massage, $level){
		$logStr = "";
		if(!empty($level)){
			if(Logger::LOGGING_LEVEL < $level){
				return;
			}
			$refClass = new ReflectionClass ('Logger');
			$constants = $refClass->getConstants();
			foreach ( $constants as $name => $value )
			{
				if ( $value == $level )
				{
					$levelStr = $name;
					break;
				}
			}
			$logStr .= "$levelStr: ";
		}
		
		$file = "";
		$line = "";
		$class = "";
		$function = "";
		$debugArr = debug_backtrace();
		
		foreach($debugArr as $trace){
			// if "file" isn't set already, set file and line as the first trace that differ from logger (the closest)
			if(empty($file) && array_key_exists("file", $trace) && strpos($trace["file"], "Logger")===false){
				$path = $trace["file"];
				$file = basename($path, ".php");
				$line = $trace["line"];
			}
			
			// same for "class" - set the first that is not "Logger"
			if(empty($class) && array_key_exists("class", $trace) && strcmp($trace["class"], "Logger")!==0){
				$class = $trace["class"];
			}
			
			// for function - set the first that is not "log" or the function (level) called - e.g. info, error, etc.
			if(empty($function) && array_key_exists("function", $trace) && strcasecmp($trace["function"], "log")!==0 && strcasecmp($trace["function"], $levelStr)!==0 && strcasecmp($trace["function"], "include_once")!==0){
				$function = $trace["function"];
			}
		}

		if(!empty($file)){			
			$logStr .= "[file:" . $file . "] ";
		}
		
		if(!empty($line)){
			$logStr .= "[line:" . $line . "] ";
		}
		
		if(!empty($class)){
			$logStr .= "[class:" . $class . "] ";
		}
		
		if(!empty($function)){
			$logStr .= "[function:" . $function . "] ";
		}

		
		$logStr .= $massage;
		error_log($logStr);
	}
	
	static function trace($massage, $debugArr=null){
		Logger::log($massage, Logger::TRACE);	
	}
	
	static function debug($massage, $debugArr=null){
		Logger::log($massage, Logger::DEBUG);
	}
	
	static function info($massage, $debugArr=null){
		Logger::log($massage, Logger::INFO);
	}
	
	static function warn($massage, $debugArr=null){
		Logger::log($massage, Logger::WARN);
	}
	
	static function error($massage, $debugArr=null){
		Logger::log($massage, Logger::ERROR);
	}
	
	static function fatal($massage, $debugArr=null){
		Logger::log($massage, Logger::FATAL);
	}
	
}